/*****************************************************************************
 * plum_kernel_hdl.c
 *
 * Copyright (C) 2020 Jeasonvor 1101627719@qq.com
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 ****************************************************************************/

/*****************************************************************************
 * Included Files
 ****************************************************************************/
#include "plum_api.h"

/*****************************************************************************
 * Trace Definitions
 ****************************************************************************/

/*****************************************************************************
 * Pre-processor Definitions
 ****************************************************************************/

/*****************************************************************************
 * Private Types
 ****************************************************************************/

/**
 * @brief:  此结构将plum内核的所有句柄进行统一管理，各种类型的handle都
 *          保存在data指针上，并向上抛出一个u32类型的虚拟ID供上层寻址
 *
 * @param:  id      -       plum内核handle ID
 * @param:  data    -       上层需要保存的数据指针，必须要长久存在
 *                          不能是栈指针
 * @param:  list    -       链表指针
 */
typedef struct {
    plum_u32         id;
    plum_void *      data;
    struct list_head list;
} plum_handle_t;

/*****************************************************************************
 * Private Function Prototypes
 ****************************************************************************/

/*****************************************************************************
 * Private Data
 ****************************************************************************/

PLUM_PRIVATE
plum_handle_t hdl_head = {
    .id        = 0,
    .data      = plum_null,
    .list.next = &hdl_head.list,
    .list.prev = &hdl_head.list,
};

/*****************************************************************************
 * Public Data
 ****************************************************************************/

/*****************************************************************************
 * Private Functions
 ****************************************************************************/

/*****************************************************************************
 * Public Functions
 ****************************************************************************/
PLUM_PUBLIC
plum_s32 plum_handle_register(plum_void *data)
{
    plum_handle_t *hdl = plum_kal_mem_malloc(sizeof(plum_handle_t));
    if (!hdl) {
        return (PLUM_ECODE_EMEM);
    }

    hdl->id   = ++hdl_head.id;
    hdl->data = data;
    list_add(&hdl->list, &hdl_head.list);

    return (hdl->id);
}

PLUM_PUBLIC
plum_s32 plum_handle_delete(plum_u32 id)
{
    struct list_head *pos;
    list_for_each(pos, &hdl_head.list)
    {
        plum_handle_t *hdl = list_entry(pos, plum_handle_t, list);
        if (hdl->id == id) {
            list_del(&hdl->list);
            plum_kal_mem_free(hdl);
            return (PLUM_ECODE_OK);
        }
    }
    return (PLUM_ECODE_UNK);
}

PLUM_PUBLIC
plum_s32 plum_handle_modify(plum_u32 id, plum_void *data)
{
    struct list_head *pos;
    list_for_each(pos, &hdl_head.list)
    {
        plum_handle_t *hdl = list_entry(pos, plum_handle_t, list);
        if (hdl->id == id) {
            plum_kal_mem_free(hdl->data);
            hdl->data = data;
            return (PLUM_ECODE_OK);
        }
    }
    return (PLUM_ECODE_UNK);
}

PLUM_PUBLIC
plum_void *plum_handle_find(plum_u32 id)
{
    struct list_head *pos;
    list_for_each(pos, &hdl_head.list)
    {
        plum_handle_t *hdl = list_entry(pos, plum_handle_t, list);
        if (hdl->id == id) {
            return (hdl->data);
        }
    }
    return (plum_null);
}

/****************************************************************************/
/*                                                                          */
/*  End of file.                                                            */
/*                                                                          */
/****************************************************************************/
